/**
 * ============万年历服务模块开始===========
 * 万年历服务 - Lunar Calendar Service
 * 
 * 功能说明：
 * - 基于lunar-javascript库实现农历计算功能
 * - 提供公历与农历的相互转换
 * - 计算传统节气、节日、宜忌等信息
 * - 支持生辰八字、五行、生肖等命理学计算
 * 
 * 依赖模块：
 * - lunar-javascript: 专业的农历计算库，支持完整的中国传统历法
 * 
 * 核心功能：
 * - 公历农历转换：精确的日期转换算法
 * - 节气计算：二十四节气的精确时间
 * - 节日查询：传统节日和现代节假日
 * - 宜忌分析：每日宜做和忌做的事项
 * - 八字计算：年月日时的天干地支
 * - 五行分析：五行属性和相生相克关系
 * - 星宿计算：二十八星宿的轮转
 * 
 * 应用场景：
 * - 万年历应用的核心数据源
 * - 命理学分析的基础数据
 * - 传统文化应用的日期计算
 * - 农业生产的节气指导
 * 
 * Based on lunar-javascript library for comprehensive lunar calendar calculations
 */

// 导入lunar-javascript库的核心模块 - Import core modules from lunar-javascript library
import { Lunar, Solar, HolidayUtil } from 'lunar-javascript';

/**
 * 万年历服务类 - Lunar Calendar Service Class
 * 
 * 该类封装了所有与农历计算相关的功能
 * 提供了完整的中国传统历法计算能力
 * 
 * 设计原则：
 * - 数据准确性：基于权威的农历算法，确保计算结果准确
 * - 功能完整性：涵盖农历计算的各个方面
 * - 易用性：提供简洁的API接口
 * - 性能优化：合理的缓存和计算优化
 * - 文化传承：保持传统文化的完整性和准确性
 */
class LunarService {
  /**
   * ============获取万年历信息功能开始===========
   * 获取指定日期的万年历信息
   * Get comprehensive lunar calendar information for specified date
   * 
   * @param {number} year - 公历年份，范围通常为1900-2100
   * @param {number} month - 公历月份，范围1-12
   * @param {number} day - 公历日期，范围1-31（根据月份而定）
   * @returns {Object} 万年历信息对象，包含农历、节气、宜忌等完整信息
   * @throws {Error} 当输入参数无效或计算失败时抛出异常
   * 
   * 功能说明：
   * - 将公历日期转换为农历日期
   * - 计算该日期的天干地支（年月日时）
   * - 获取节气信息和下一个节气
   * - 查询传统节日和现代节假日
   * - 分析当日宜做和忌做的事项
   * - 计算五行属性和生肖信息
   * - 获取星宿和神煞信息
   * 
   * 返回数据结构：
   * {
   *   solar: {           // 公历信息
   *     year: number,    // 公历年
   *     month: number,   // 公历月
   *     day: number,     // 公历日
   *     weekDay: string, // 星期几
   *     isLeapYear: boolean // 是否闰年
   *   },
   *   lunar: {           // 农历信息
   *     year: number,    // 农历年
   *     month: number,   // 农历月
   *     day: number,     // 农历日
   *     monthName: string, // 农历月份名称
   *     dayName: string,   // 农历日期名称
   *     isLeapMonth: boolean // 是否闰月
   *   },
   *   ganZhi: {          // 天干地支
   *     year: string,    // 年柱
   *     month: string,   // 月柱
   *     day: string,     // 日柱
   *     time: string     // 时柱（需要具体时间）
   *   },
   *   wuXing: {          // 五行信息
   *     year: string,    // 年五行
   *     month: string,   // 月五行
   *     day: string,     // 日五行
   *     naYin: string    // 纳音五行
   *   },
   *   zodiac: string,    // 生肖
   *   jieQi: {           // 节气信息
   *     current: string, // 当前节气
   *     next: string,    // 下一节气
   *     nextDate: string // 下一节气日期
   *   },
   *   festivals: {       // 节日信息
   *     traditional: [], // 传统节日
   *     modern: [],      // 现代节假日
   *     solar: []        // 公历节日
   *   },
   *   suitable: [],      // 宜做事项
   *   unsuitable: [],    // 忌做事项
   *   luckyDirection: string, // 吉利方位
   *   constellation: string,  // 星宿
   *   godPosition: {     // 神位
   *     xi: string,      // 喜神方位
   *     fu: string,      // 福神方位
   *     cai: string      // 财神方位
   *   }
   * }
   * 
   * 使用示例：
   * const lunarService = new LunarService();
   * const info = lunarService.getCalendarInfo(2024, 1, 15);
   * console.log(info.lunar.monthName); // 输出：腊月
   * console.log(info.ganZhi.day); // 输出：甲子
   * 
   * 异常处理：
   * - 参数验证失败：年月日参数缺失或格式错误
   * - 日期无效：如2月30日等不存在的日期
   * - 计算错误：lunar-javascript库内部计算异常
   * 
   * 性能考虑：
   * - 对于频繁查询的日期，可以考虑添加缓存机制
   * - lunar-javascript库已经过优化，计算性能良好
   * - 避免在循环中重复创建Solar对象
   */
  getCalendarInfo(year, month, day) {
    try {
      // 第一步：参数验证 - Step 1: Parameter validation
      if (!year || !month || !day) {
        throw new Error('年月日参数不能为空 - Year, month, and day parameters cannot be empty');
      }
      
      // 验证参数类型和范围 - Validate parameter types and ranges
      if (typeof year !== 'number' || typeof month !== 'number' || typeof day !== 'number') {
        throw new Error('年月日参数必须为数字类型 - Year, month, and day must be numbers');
      }
      
      if (year < 1900 || year > 2100) {
        throw new Error('年份范围应在1900-2100之间 - Year should be between 1900-2100');
      }
      
      if (month < 1 || month > 12) {
        throw new Error('月份范围应在1-12之间 - Month should be between 1-12');
      }
      
      if (day < 1 || day > 31) {
        throw new Error('日期范围应在1-31之间 - Day should be between 1-31');
      }
      
      // 第二步：创建公历日期对象 - Step 2: Create solar date object
      // Solar.fromYmd() 创建公历日期对象，这是所有计算的基础
      const solar = Solar.fromYmd(year, month, day);
      
      // 验证日期是否有效（如检查2月30日这种无效日期）
      if (!solar) {
        throw new Error('无效的日期 - Invalid date');
      }
      
      // 第三步：转换为农历 - Step 3: Convert to lunar calendar
      // getLunar() 方法将公历日期转换为对应的农历日期
      // 这个转换考虑了闰月、大小月等复杂的农历规则
      const lunar = solar.getLunar();
      
      // 第四步：获取节假日信息 - Step 4: Get holiday information
      // HolidayUtil.getHolidays() 获取指定日期的所有节假日
      // 包括传统节日、现代节假日、调休等信息
      const holidays = HolidayUtil.getHolidays(year, month, day);
      
      // 第五步：获取节气信息 - Step 5: Get solar terms information
      // 节气是中国传统历法的重要组成部分，用于指导农业生产
      const jieQi = lunar.getJieQi();           // 当前节气
      const nextJieQi = lunar.getNextJie();     // 下一个节气
      const nextJieQiDate = lunar.getNextJie(true); // 下一个节气的具体日期
      
      // 第六步：获取生肖信息 - Step 6: Get zodiac information
      // 生肖按农历年计算，需要注意立春前后的年份归属
      const zodiac = lunar.getYearShengXiao();
      
      // 第七步：获取天干地支 - Step 7: Get heavenly stems and earthly branches
      // 天干地支是中国传统的纪年、纪月、纪日、纪时系统
      const yearGanZhi = lunar.getYearInGanZhi();   // 年柱
      const monthGanZhi = lunar.getMonthInGanZhi(); // 月柱
      const dayGanZhi = lunar.getDayInGanZhi();     // 日柱
      
      // 第八步：获取五行信息 - Step 8: Get five elements information
      // 五行理论是中国传统哲学的重要组成部分
      const yearWuXing = lunar.getYearNaYin();      // 年纳音五行
      const dayWuXing = lunar.getDayNaYin();        // 日纳音五行
      
      // 第九步：获取宜忌信息 - Step 9: Get suitable and unsuitable activities
      // 宜忌是传统历法中指导日常活动的重要内容
      const yi = lunar.getDayYi();                  // 宜做的事项
      const ji = lunar.getDayJi();                  // 忌做的事项
      
      // 第十步：获取吉神宜趋和凶神宜忌 - Step 10: Get auspicious and inauspicious gods
      const jiShen = lunar.getDayJiShen();          // 吉神宜趋
      const xiongSha = lunar.getDayXiongSha();      // 凶神宜忌
      
      // 第十一步：获取星宿信息 - Step 11: Get constellation information
      // 二十八星宿是中国传统天文学的重要概念
      const xiu = lunar.getXiu();                   // 当日星宿
      const zheng = lunar.getZheng();               // 星宿属性
      const animal = lunar.getAnimal();             // 星宿动物
      const gong = lunar.getGong();                 // 星宿宫位
      const shou = lunar.getShou();                 // 星宿守护
      
      // 第十二步：获取神位方向 - Step 12: Get god positions
      // 传统文化中不同神位在不同日期有不同的方位
      const xiShenFangWei = lunar.getDayPositionXi();      // 喜神方位
      const fuShenFangWei = lunar.getDayPositionFu();      // 福神方位
      const caiShenFangWei = lunar.getDayPositionCai();    // 财神方位
      const taiSuiFangWei = lunar.getDayPositionTaiSui();  // 太岁方位
      
      // 第十三步：获取时辰信息 - Step 13: Get time period information
      // 传统将一天分为12个时辰，每个时辰有不同的宜忌
      const timeGanZhi = [];
      for (let i = 0; i < 12; i++) {
        const timeIndex = i * 2; // 每个时辰对应2小时
        const lunarTime = lunar.getTimeInGanZhi(timeIndex);
        timeGanZhi.push({
          time: `${timeIndex}:00-${(timeIndex + 2) % 24}:00`,
          ganZhi: lunarTime,
          name: this.getTimeChineseName(i)
        });
      }
      
      // 第十四步：构建返回数据 - Step 14: Build return data
      const result = {
        // 公历信息 - Solar calendar information
        solar: {
          year: solar.getYear(),
          month: solar.getMonth(),
          day: solar.getDay(),
          weekDay: solar.getWeekInChinese(),
          weekDayIndex: solar.getWeek(),
          isLeapYear: solar.isLeapYear(),
          dayOfYear: solar.getDaysInYear(),
          weekOfYear: solar.getWeeksInYear()
        },
        
        // 农历信息 - Lunar calendar information
        lunar: {
          year: lunar.getYear(),
          month: lunar.getMonth(),
          day: lunar.getDay(),
          monthName: lunar.getMonthInChinese(),
          dayName: lunar.getDayInChinese(),
          isLeapMonth: lunar.isLeapMonth(),
          yearName: lunar.getYearInChinese(),
          monthDays: lunar.getDaysInMonth()
        },
        
        // 天干地支信息 - Heavenly stems and earthly branches
        ganZhi: {
          year: yearGanZhi,
          month: monthGanZhi,
          day: dayGanZhi,
          timeList: timeGanZhi
        },
        
        // 五行信息 - Five elements information
        wuXing: {
          year: yearWuXing,
          day: dayWuXing,
          yearElement: lunar.getYearShengXiao(),
          dayElement: lunar.getDayShengXiao()
        },
        
        // 生肖信息 - Zodiac information
        zodiac: zodiac,
        
        // 节气信息 - Solar terms information
        jieQi: {
          current: jieQi,
          next: nextJieQi,
          nextDate: nextJieQiDate ? nextJieQiDate.toYmd() : null
        },
        
        // 节日信息 - Festival information
        festivals: {
          traditional: lunar.getFestivals(),        // 传统节日
          modern: holidays || [],                   // 现代节假日
          solar: solar.getFestivals()              // 公历节日
        },
        
        // 宜忌信息 - Suitable and unsuitable activities
        activities: {
          suitable: yi || [],                       // 宜做事项
          unsuitable: ji || [],                     // 忌做事项
          auspiciousGods: jiShen || [],            // 吉神宜趋
          inauspiciousGods: xiongSha || []         // 凶神宜忌
        },
        
        // 星宿信息 - Constellation information
        constellation: {
          xiu: xiu,                                // 星宿
          zheng: zheng,                            // 星宿属性
          animal: animal,                          // 星宿动物
          gong: gong,                              // 星宿宫位
          shou: shou                               // 星宿守护
        },
        
        // 神位方向 - God positions
        godPositions: {
          xi: xiShenFangWei,                       // 喜神方位
          fu: fuShenFangWei,                       // 福神方位
          cai: caiShenFangWei,                     // 财神方位
          taiSui: taiSuiFangWei                    // 太岁方位
        },
        
        // 其他信息 - Other information
        other: {
          pengZu: lunar.getPengZuGan() + ' ' + lunar.getPengZuZhi(), // 彭祖百忌
          chong: lunar.getDayChong(),              // 冲煞
          sha: lunar.getDaySha(),                  // 煞向
          wuXingJiazi: lunar.getDayNaYin(),        // 日纳音
          jiuXing: lunar.getDayJiuXing(),          // 九星
          liuYao: lunar.getDayLiuYao()             // 六曜
        }
      };
      
      return result;
      
    } catch (error) {
      // 第十五步：错误处理 - Step 15: Error handling
      console.error('获取万年历信息失败 - Failed to get lunar calendar information:', error);
      throw new Error(`万年历计算失败: ${error.message}`);
    }
  }
  
  /**
   * ============获取时辰中文名称功能开始===========
   * 获取时辰的中文名称
   * Get Chinese name for time period
   * 
   * @param {number} timeIndex - 时辰索引（0-11）
   * @returns {string} 时辰中文名称
   * 
   * 时辰对照表：
   * 0: 子时 (23:00-01:00)
   * 1: 丑时 (01:00-03:00)
   * 2: 寅时 (03:00-05:00)
   * 3: 卯时 (05:00-07:00)
   * 4: 辰时 (07:00-09:00)
   * 5: 巳时 (09:00-11:00)
   * 6: 午时 (11:00-13:00)
   * 7: 未时 (13:00-15:00)
   * 8: 申时 (15:00-17:00)
   * 9: 酉时 (17:00-19:00)
   * 10: 戌时 (19:00-21:00)
   * 11: 亥时 (21:00-23:00)
   */
  getTimeChineseName(timeIndex) {
    const timeNames = [
      '子时', '丑时', '寅时', '卯时', '辰时', '巳时',
      '午时', '未时', '申时', '酉时', '戌时', '亥时'
    ];
    return timeNames[timeIndex] || '未知时辰';
  }
  
  /**
   * ============获取月份万年历信息功能开始===========
   * 获取整个月份的万年历信息
   * Get lunar calendar information for entire month
   * 
   * @param {number} year - 公历年份
   * @param {number} month - 公历月份
   * @returns {Array} 月份中每一天的万年历信息数组
   * @throws {Error} 当参数无效时抛出异常
   * 
   * 功能说明：
   * - 获取指定月份中每一天的完整万年历信息
   * - 适用于月历显示和批量数据处理
   * - 自动处理大小月和闰年的天数差异
   * 
   * 使用示例：
   * const monthInfo = lunarService.getMonthCalendarInfo(2024, 1);
   * console.log(monthInfo.length); // 输出：31（1月有31天）
   */
  getMonthCalendarInfo(year, month) {
    try {
      // 参数验证
      if (!year || !month) {
        throw new Error('年份和月份参数不能为空');
      }
      
      // 获取该月的天数
      const solar = Solar.fromYmd(year, month, 1);
      const daysInMonth = solar.getDaysInMonth();
      
      // 获取每一天的万年历信息
      const monthData = [];
      for (let day = 1; day <= daysInMonth; day++) {
        const dayInfo = this.getCalendarInfo(year, month, day);
        monthData.push(dayInfo);
      }
      
      return monthData;
      
    } catch (error) {
      console.error('获取月份万年历信息失败:', error);
      throw new Error(`月份万年历计算失败: ${error.message}`);
    }
  }
  
  /**
   * ============农历转公历功能开始===========
   * 将农历日期转换为公历日期
   * Convert lunar date to solar date
   * 
   * @param {number} lunarYear - 农历年份
   * @param {number} lunarMonth - 农历月份
   * @param {number} lunarDay - 农历日期
   * @param {boolean} isLeapMonth - 是否闰月，默认false
   * @returns {Object} 公历日期信息
   * @throws {Error} 当转换失败时抛出异常
   * 
   * 功能说明：
   * - 将农历日期精确转换为对应的公历日期
   * - 正确处理闰月的情况
   * - 返回完整的公历日期信息
   * 
   * 使用示例：
   * const solarDate = lunarService.lunarToSolar(2024, 1, 1, false);
   * console.log(solarDate); // 输出对应的公历日期
   */
  lunarToSolar(lunarYear, lunarMonth, lunarDay, isLeapMonth = false) {
    try {
      // 创建农历日期对象
      const lunar = Lunar.fromYmd(lunarYear, lunarMonth, lunarDay, isLeapMonth);
      
      // 转换为公历
      const solar = lunar.getSolar();
      
      return {
        year: solar.getYear(),
        month: solar.getMonth(),
        day: solar.getDay(),
        weekDay: solar.getWeekInChinese(),
        isLeapYear: solar.isLeapYear()
      };
      
    } catch (error) {
      console.error('农历转公历失败:', error);
      throw new Error(`农历转公历失败: ${error.message}`);
    }
  }
  
  /**
   * ============获取生肖运势功能开始===========
   * 获取指定生肖的运势信息
   * Get fortune information for specified zodiac
   * 
   * @param {string} zodiac - 生肖名称
   * @param {string} date - 日期，格式YYYY-MM-DD
   * @returns {Object} 生肖运势信息
   * 
   * 功能说明：
   * - 基于传统生肖理论计算运势
   * - 结合当日的天干地支分析
   * - 提供简化的运势参考信息
   * 
   * 注意：这是一个简化的实现，真实的运势计算需要更复杂的算法
   */
  getZodiacFortune(zodiac, date) {
    try {
      // 解析日期
      const [year, month, day] = date.split('-').map(Number);
      const calendarInfo = this.getCalendarInfo(year, month, day);
      
      // 简化的生肖运势计算
      // 实际应用中需要更复杂的算法
      const fortune = {
        zodiac: zodiac,
        date: date,
        overall: Math.floor(Math.random() * 100) + 1, // 模拟总体运势
        career: Math.floor(Math.random() * 100) + 1,  // 模拟事业运
        wealth: Math.floor(Math.random() * 100) + 1,  // 模拟财运
        love: Math.floor(Math.random() * 100) + 1,    // 模拟感情运
        health: Math.floor(Math.random() * 100) + 1,  // 模拟健康运
        luckyColor: ['红色', '黄色', '绿色', '蓝色', '紫色'][Math.floor(Math.random() * 5)],
        luckyNumber: Math.floor(Math.random() * 9) + 1,
        advice: '今日宜保持平和心态，谨慎行事。',
        ganZhi: calendarInfo.ganZhi.day
      };
      
      return fortune;
      
    } catch (error) {
      console.error('获取生肖运势失败:', error);
      throw new Error(`生肖运势计算失败: ${error.message}`);
    }
  }
}

// 导出服务实例 - Export service instance
// 使用单例模式，确保整个应用中只有一个实例
export default new LunarService();